#pragma once

class  HashTableEntry
{
public:
	 HashTableEntry();
	virtual ~ HashTableEntry();

	virtual unsigned CalcHashCode() = 0;

	virtual bool Equal(const HashTableEntry* pEntry) = 0;

	unsigned GetHashCode() { return m_hashValue;}
	void SetHashCode(unsigned hashValue) { m_hashValue = hashValue;}

	HashTableEntry* GetNext() { return m_pNext;}
	HashTableEntry** GetNextP() { return &m_pNext;}
	void SetNext(HashTableEntry* pNext) { m_pNext = pNext;}
private:
	HashTableEntry* m_pNext;
	unsigned m_hashValue;
};

class HashTable
{
public:
	HashTable();
	~HashTable();

public:
	//
	void SetLoad(float fLoad = 0.5) { m_fLoad = fLoad;}
public:
	//
	void Insert(HashTableEntry* pEntry);
	//
	HashTableEntry* Remove(HashTableEntry* pEntry);
	//
	HashTableEntry* Find(HashTableEntry* pEntry);
	//
	HashTableEntry** FindP(HashTableEntry* pEntry);
	//
	void Remove();
private:
	//
	bool Grow(unsigned size);
	//
	HashTableEntry** Bucket(unsigned hashValue);

private:
	HashTableEntry** m_Table;
	unsigned m_nLength;
	unsigned m_nEntries;
	unsigned m_nLimit;
	int m_PrimeIdx;
	float m_fLoad;
private:
	static unsigned s_primes[];
};

